<?php
/**
 * 辅助类
 * @author zzy
 *
 */

class Helper {
	/**
	 * CURL请求
	 * @param unknown $durl
	 * @param array $data
	 * @param array $header
	 */
	public static function curl_file_get_contents($durl,$data=array(), $header = array()){
		$ch = curl_init();
		if (!empty($header)) {
		    curl_setopt($ch, CURLOPT_HTTPHEADER, $header);
		}
		
		curl_setopt($ch, CURLOPT_URL, $durl);
		curl_setopt($ch, CURLOPT_TIMEOUT, 4);
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0);
		curl_setopt($ch, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
		if(!empty($data))
		{
			curl_setopt ($ch,CURLOPT_POST,1);
			curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
		}
		curl_setopt ( $ch, CURLOPT_HEADER, 0 );
		$r = curl_exec($ch);
		curl_close($ch);
		return $r;
	}
	
	/**
	 * 不转义中文字符和\/的 json 编码方法，现在主要用在验证signature上
	 * @author gxd
	 * @param array $arr 待编码数组
	 * @return string
	 */
	public static function json_encode_no_zh($arr) {
		$str = str_replace ( "\\/", "/", json_encode ( $arr ) );
		$search = '#\\\u([0-9a-f]+)#ie';
	
		if (strpos (strtoupper(PHP_OS), 'WIN' ) === false) {
			$replace = "iconv('UCS-2BE', 'UTF-8', pack('H4', '\\1'))";//LINUX
		} else {
			$replace = "iconv('UCS-2', 'UTF-8', pack('H4', '\\1'))";//WINDOWS
		}
	
		return @preg_replace ( $search, $replace, $str );
	}
	
	/**
	 * 处理前台显示时间     XX分钟前   XX小时前    一天前的直接显示时间
	 * @param unknown $time
	 * @return Ambigous <string, unknown>
	 */
	public static function formatShowTime($time)
	{
	    $result = "";
	    $nowTime = strtotime(date("Y-m-d H:i:s",time()));
	    $time_str = strtotime($time);
	    $restTime = $nowTime-$time_str;
	    if($restTime>86400){
	        $result = $time;
	    }elseif($restTime<3600){
	        $result = ceil($restTime/60)."分钟前";
	    }else{
	        $result = ceil($restTime/3600)."小时前";
	    }
	    return $result;
	}
	
	/**
	 * 双向加密函数
	 * @param unknown $string
	 * @param string $operation
	 * @param string $key
	 * @param number $expiry
	 * @return string
	 */
	public static function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {
		$key = empty($key)?'!Ha@io#o2$01%4':$key;
		if($operation == 'DECODE') {
			//如果是解密，则先从安全的URL中转换回来
			$string = str_replace(array('-','_'),array('+','/'),$string);
			$mod4 = strlen($string) % 4;
			if ($mod4) {
				$string .= substr('====', $mod4);
			}
		}
		// 动态密匙长度，相同的明文会生成不同密文就是依靠动态密匙
		$ckey_length = 4;
	
		// 密匙
		$key = md5($key ? $key : $GLOBALS['discuz_auth_key']);
	
		// 密匙a会参与加解密
		$keya = md5(substr($key, 0, 16));
		// 密匙b会用来做数据完整性验证
		$keyb = md5(substr($key, 16, 16));
		// 密匙c用于变化生成的密文
		$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';
		// 参与运算的密匙
		$cryptkey = $keya.md5($keya.$keyc);
		$key_length = strlen($cryptkey);
		// 明文，前10位用来保存时间戳，解密时验证数据有效性，10到26位用来保存$keyb(密匙b)，解密时会通过这个密匙验证数据完整性
		// 如果是解码的话，会从第$ckey_length位开始，因为密文前$ckey_length位保存 动态密匙，以保证解密正确
		$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;
		$string_length = strlen($string);
		$result = '';
		$box = range(0, 255);
		$rndkey = array();
		// 产生密匙簿
		for($i = 0; $i <= 255; $i++) {
			$rndkey[$i] = ord($cryptkey[$i % $key_length]);
		}
		// 用固定的算法，打乱密匙簿，增加随机性，好像很复杂，实际上对并不会增加密文的强度
		for($j = $i = 0; $i < 256; $i++) {
			$j = ($j + $box[$i] + $rndkey[$i]) % 256;
			$tmp = $box[$i];
			$box[$i] = $box[$j];
			$box[$j] = $tmp;
		}
		// 核心加解密部分
		for($a = $j = $i = 0; $i < $string_length; $i++) {
			$a = ($a + 1) % 256;
			$j = ($j + $box[$a]) % 256;
			$tmp = $box[$a];
			$box[$a] = $box[$j];
			$box[$j] = $tmp;
			// 从密匙簿得出密匙进行异或，再转成字符
			$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
		}
		if($operation == 'DECODE') {
			// substr($result, 0, 10) == 0 验证数据有效性
			// substr($result, 0, 10) - time() > 0 验证数据有效性
			// substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16) 验证数据完整性
			// 验证数据有效性，请看未加密明文的格式
			if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {
				return substr($result, 26);
			} else {
				return '';
			}
		} else {
			// 把动态密匙保存在密文里，这也是为什么同样的明文，生产不同密文后能解密的原因
			// 因为加密后的密文可能是一些特殊字符，复制过程可能会丢失，所以用base64编码
			$str = $keyc.str_replace('=', '', base64_encode($result));
	
			//转换下防止url传输出错
			$str = str_replace(array('+','/','='),array('-','_',''),$str);
	
			return $str;
		}
	}
	
	/**
	 * @param unknown_type 数组转换为对象
	 */
	public static function arrayToObject($e){
		if( gettype($e)!='array' ) return;
		foreach($e as $k=>$v){
			if( gettype($v)=='array' || getType($v)=='object' )
				$e[$k]=(object)self::arrayToObject($v);
		}
		return (object)$e;
	}
	
	/**
	 * @param unknown_type $e 对象转换数组
	 * @return void|array 
	 */
	public static function objectToArray($e){
		$e=(array)$e;
		foreach($e as $k=>$v){
			if( gettype($v)=='resource' ) return;
			if( gettype($v)=='object' || gettype($v)=='array' )
				$e[$k]=(array)self::objectToArray($v);
		}
		return $e;
	}
	
	/**
	 * 格式化价格
	 * 	去掉后面.00
	 * @param unknown $price
	 */
	public static function formatPrice($price)
	{
		$priceInt = intval($price);
		if($price == $priceInt)
		{
			$price = $priceInt;
		}
		$price = floatval($price);
		return $price;
	}
	
	/**
	 * 验证邮箱.
	 *
	 * @param unknown_type $email
	 */
	public static function checkEmail($email)
	{
		if (!empty($email) && preg_match('#^[\w\.\-]+@[\w\-]+(\.[\w\-]+)+$#', $email)) return true;
		return false;
	}
	
	/**
	 * 验证用户名,只允许数字,字母,中文,短横线,下划线.
	 *
	 * @param unknown_type $userName
	 */
	public static function checkUserName($userName)
	{
		if (!empty($userName) && preg_match('#^[A-Za-z0-9\x80-\xff\-\_]{4,30}$#', $userName) !== false) return true;
		return false;
	}
	
	/**
	 * 检查号.格式为:12345678901
	 *
	 * @param unknown_type $mobile
	 */
	public static function checkPhone($mobile)
	{
		if (!empty($mobile) && preg_match('/^1[345678]\d{9}$/', $mobile)) return true;
		return false;
	}

	/**
	 * 将字符串由实体进行反解
	 * @param unknown $str
	 */
	public static function dehtmlspecialchars($str){
		if($str==''){
			return '';
		}
		//$entities = get_html_translation_table(HTML_ENTITIES);
		$entities = array(
			'&nbsp;'	=> ' ',
			'&quot'  	=> '"',
			'&amp;'	=> '&',
			'&lt;'			=> '<',
			'&gt;'		=> '>',
		);//支持常见即可,太多耗资源
		$str = str_replace(array_keys($entities), array_values($entities), $str);
		return $str;
	}
	
	/**
	 * 隐藏手机号码中间部分
	 * @param unknown $mobile
	 */
	public static function hideMobile($mobile)
	{
	    $mobile = substr($mobile,0,3).'****'.substr($mobile, -3);
	    return $mobile;
	}
	
	/**
	 * 隐藏邮箱
	 * @param unknown $email
	 */
	public static function hideEmail($email) 
	{
	    $arr = explode('@', $email);
	    if (strlen($arr[0]) > 3) {
	        $arr[0] = substr($arr[0], 0, 3);
	    } else {
	        $arr[0] = substr($arr[0], 0, 1);
	    }
	    
	    $email = $arr[0].'****@'.$arr[1];
	    return $email;
	}
	
	/**
	 * 隐藏用户姓名/邮箱/电话/银行卡号
	 * @param unknown $name
	 * @return string|unknown
	 */
	public static function hideUserShowInfo($name) {
		if (self::checkPhone($name)) {
			return self::hideMobile($name);
		} elseif (self::checkEmail($name)) {
			return self::hideEmail($name);
		} elseif (is_numeric($name) && (strlen($name)==16 || strlen($name)==19)) {//银行卡
			return substr($name, 0, 3)."***".substr($name, -3);
		} else {
			return mb_substr($name, 0, 1, 'utf-8')."*";
		}
	}
	
	/**
	 * 获取邮件/短信模板内容
	 * @param unknown $flag
	 */
	public static function getMailMod($flag)
	{
	    global $db;
	    $sql = "select subject,message from ".MAILMOD." where flag='{$flag}'";
	    $db->query($sql);
	    $res = $db->fetchRow();
	    
	    return $res;
	}
	
	/**
	 * 获取某推送信息内容
	 * @param unknown $flag 模板标识
	 * @param unknown $replaceArr 需要替换字符对应的数组
	 */
	public static function getMessageDetail($flag,$replaceArr)
	{
	    $message = self::getMailMod($flag);
	    if(!empty($message)){
	        //开始替换
	        if(!empty($replaceArr)){
	            foreach ($replaceArr as $k=>$v)
	            {
	                $need_replace = [];
	                if(isset($message[$k])){
	                    preg_match_all('/(\{\{(\w+)\}\})/', $message[$k],$need_replace);
	                    foreach ($need_replace[0] as $vv)
	                    {
	                        $replaceStr = '';
	                        if(isset($v[$vv])){
	                            $replaceStr = $v[$vv];
	                        }
                            $message[$k] = str_replace($vv, $replaceStr, $message[$k]);
	                    }
	                }
	            }
	        }
	    }
	    
	    return $message;
	}
	
	/**
	 * 推送微信消息
	 * @param unknown $flag
	 * @param unknown $param
	 */
	public static function pushMessage($flag,$replaceArr,$param)
	{
	    global $config;
	    
	    $message = self::getMessageDetail($flag, $replaceArr);
	    if(!empty($message)){//调用接口
	        include_once($config["webroot"]."/lib/Api.php");
	        $param['first'] = $message['subject'];
	        $param['remark'] = $message['message'];
	        
	        //发短信
	        if ($flag == 'openShopSuccessSelf') {
	            self::sendMobileMessage($param['memberId'], 'openShopMsg');
	        }
	        
	        //开店模板
	        if($flag=='openShopSuccessSelf'){
	            $flag = 'openShopSuccess';
	        }
	        
	        $result = Api::callItemApi('Weixin', 'msgPush', ["memberId"=>$param['memberId'],"msgType"=>$flag,"msgJson"=>json_encode($param)]);
	        
	        
	        //写日志
	        $data['param'] = ["memberId"=>$param['memberId'],"msgType"=>$flag,"msgInfo"=>$param];
	        $data['result'] = $result;
	        self::writeGeneralLog('PUSH_WX_MSG', json_encode($data,JSON_UNESCAPED_UNICODE), '1');
	        
	        return $result;
	    }
	    
	    return ['code'=>1122,'msg'=>'未找到消息模板，推送消息为空'];
	}
	
	/**
	 * 写日志
	 * @param unknown $type
	 * @param unknown $data
	 * @param unknown $status
	 */
	public static function writeGeneralLog($type,$data,$status){
	    global $db;
	    
	    $data = @mysql_escape_string($data);
	    $sql = "insert into haiou_general_log (`type`,`data`,`status`) values('{$type}','{$data}','$status')";
	    $db->query($sql);
	    $id = $db->lastid();
	    
	    return $id;
	}
	
	/**
	 * 发送手机短信
	 * @param unknown $memberId
	 * @param unknown $flag
	 * @param unknown $platform 默认为微店
	 * @param unknown $replaceArr
	 */
	public static function sendMobileMessage($memberId,$flag,$platform='microShop',$replaceArr=[]){
	    global $db,$config;
	    //短信模板
	    $message = self::getMessageDetail($flag, $replaceArr);
	    //获取手机号码
	    $sql = "select mobile from haiou_member where userid={$memberId}";
	    $db->query($sql);
	    $mobile = $db->fetchField('mobile');
	    
	    if($mobile && !empty($message)){
	        $queueData['Mobile']  = $mobile;
	        $queueData['Content'] = $message['message'];
	        if(!empty($platform)){
	           $queueData['platform'] = $platform;
	        }
	        
	        include_once("$config[webroot]/lib/Httpsqs.php");
	        Httpsqs::put('sendSMS',$queueData);
	        
	        return true;
	    }
	    return false;
	}
}
